package server.proxy;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.URL;
import java.net.UnknownHostException;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.concurrent.*;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.group.ChannelGroup;
import org.jboss.netty.channel.group.DefaultChannelGroup;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;

import server.proxy.factory.ProxyServerPipelineFactory;

/**
 * This is the main server class that starts the server.
 * 
 * @author Maxim
 *
 */
public class ProxyServer {
	
	public static ChannelGroup allChannels = new DefaultChannelGroup();
	
	
	public static void main (String[] args) throws IOException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeySpecException, IllegalBlockSizeException, BadPaddingException {
		
		
		int listenPort = Config.DEFAULT_PORT;
	
		try{
			listenPort = Integer.parseInt(args[0]);
			
		}
		catch(NumberFormatException e){
			System.out.println("Port number should be Integer. Default port set to: "+ Config.DEFAULT_PORT);
		}
		
		System.out.println("Starting server...");
		
		//loading data from files
		String tIPaddress = null; 
		switch(Config.HOW_TO_SET_IP_ADDRESS){
		
		case 1:
			tIPaddress = getExternalIP() + ":" +listenPort;
			break;
		
		case 2:
			try {

			    tIPaddress = InetAddress.getLocalHost().getHostAddress() + ":" +listenPort;
			    
			} catch (UnknownHostException e) {
			}
			break;
			
		}
		
		new ServerStarterTask(tIPaddress);
		
		
		Executor threadPool = Executors.newCachedThreadPool();
		ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(threadPool, threadPool));
		bootstrap.setPipelineFactory(new ProxyServerPipelineFactory(threadPool, tIPaddress));
		
		allChannels.add(bootstrap.bind(new InetSocketAddress(listenPort)));
		
		System.out.println("Server started, for shutdown press 5");
		
		
		//reading data from keyboard
		BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
		while(!input.readLine().equals("5")){
			input = new BufferedReader(new InputStreamReader(System.in));	
		}
		
		
		
		System.out.println("Closing Server");
		
		//closing all open channels
		allChannels.close().awaitUninterruptibly();
		bootstrap.releaseExternalResources();
		
		//saving data to files
		new ShutdownTasks();
		
		

	}
	

	/**
	 * This method checks the external IP of this machine
	 * 
	 * @return my IP address
	 * @throws IOException
	 */
	public static String getExternalIP() throws IOException{
		
		URL tWhatsMyIP = new URL("http://www.whatismyip.com/automation/n09230945.asp");
		BufferedReader in = new BufferedReader(new InputStreamReader(tWhatsMyIP.openStream()));
		return in.readLine();
	}

}
